package com.le.tester.imooc.masterJUC.lock.reentrantlock;

import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 描述：非公平锁和公平锁的策略
 */
public class NonFairBargeDemo {

    //多读，要控制成唯一写
    //不允许插队了，管你是读还是写
    private static ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
    //读
    private static ReentrantReadWriteLock.ReadLock readLock = lock.readLock();
    //写
    private static ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();

    public static void main(String[] args) {
        new Thread(NonFairBargeDemo::write, "thread1").start();
        //这个时刻，thread2是对了的头
        new Thread(NonFairBargeDemo::read, "thread2").start();
        new Thread(NonFairBargeDemo::read, "thread3").start();
        //这个时刻，thread4是队列的头
        new Thread(NonFairBargeDemo::write, "thread4").start();
        new Thread(NonFairBargeDemo::read, "thread5").start();


        //模拟1000个读的线程要进行插队了,插队到了thread2或者thread3的前面
        new Thread(new Runnable() {
            @Override
            public void run() {
                Thread[] threads = new Thread[1000];
                //让这个线程不停的读
                for (int i = 0; i < 1000; i++) {
                    threads[i] = new Thread(NonFairBargeDemo::read, "子线程创建的thread" + i);
                }
                for (int i = 0; i < 1000; i++) {
                    threads[i].start();
                }
            }
        }).start();
    }


    private static void read() {
        System.out.println(Thread.currentThread().getName() + " 开始尝试获取读锁");
        readLock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + " 得到读锁，正在读取");
            Thread.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println(Thread.currentThread().getName() + " 释放读锁");
            readLock.unlock();
        }
    }

    private static void write() {
        System.out.println(Thread.currentThread().getName() + " 开始尝试获取写锁");
        writeLock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + " 获取到了写锁");
            Thread.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println(Thread.currentThread().getName() + " 释放写锁");
            writeLock.unlock();
        }
    }
}
